package com.xh.generate.core;

import com.xh.generate.bean.ColumnInfo;
import com.xh.generate.bean.TableInfo;
import com.xh.generate.core.convertor.DatabaseType2JavaTypeConvertor;
import com.xh.generate.core.convertor.DatabaseType2JdbcTypeConvertor;
import com.xh.generate.core.convertor.TypeConvertor;
import com.xh.generate.utils.StringUtil;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @Name TableContext
 * @Description 负责获取管理数据库所有表结构和类结构的关系，并可以根据表结构生成类结构。
 * @Author wen
 * @Date 2020/3/29
 */
public class TableContext {

    /**
     * 表名为key，表信息对象为value
     */
    private static Map<String, TableInfo> tables = new HashMap<>();

    static {
        //1.获取类型转换器
//        getTypeConvertor();
        //2.将数据库信息读取到对象中
        loadDatabaseInfo();
    }

    private static void loadDatabaseInfo() {
        Connection con = null;
        try {
            //1.获取类型转换器
            TypeConvertor databaseType2JavaTypeConvertor = new DatabaseType2JavaTypeConvertor();
            TypeConvertor databaseType2JdbcTypeConvertor = new DatabaseType2JdbcTypeConvertor();
            con = DBManager.getConnection();
            DatabaseMetaData dbmd = con.getMetaData();
            ResultSet tableRet = dbmd.getTables(null, "%", "%", new String[]{"TABLE"});
            String generateTables = DBManager.getConf().getGenerateTables();
            while (tableRet.next()) {
                boolean falg;
                //1.获取数据库表
                String tableName = (String) tableRet.getObject("TABLE_NAME");
                if(StringUtil.isEmpty(generateTables) || (StringUtil.isNotEmpty(generateTables) && generateTables.contains(tableName))){
                    TableInfo tableInfo = new TableInfo(tableName, new ArrayList<>(), new LinkedHashMap<>());
                    tables.put(tableName, tableInfo);
                    //2.根据表名查询表中的所有字段
                    loadTableInfos(dbmd, tableName, tableInfo, databaseType2JavaTypeConvertor, databaseType2JdbcTypeConvertor);
                    //3.查询表中逐渐字段
                    loadTablePriKeys(dbmd, tableName, tableInfo);
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != con) con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
    * @Name loadTablePriKeys
    * @Description 查询表中逐渐字段
    * @Author wen
    * @Date 2020/3/30
    */
    private static void loadTablePriKeys(DatabaseMetaData dbmd, String tableName, TableInfo tableInfo) throws SQLException {
        ResultSet resultSet = dbmd.getPrimaryKeys(null, "%", tableName);  //查询表中的主键
        while (resultSet.next()) {
            ColumnInfo columnInfo = tableInfo.getColumns().get(resultSet.getString("COLUMN_NAME"));
            columnInfo.setKeyType(1);                                                       //设置为主键类型
            tableInfo.setPriKeyFieldType(columnInfo.getType().getFieldType());
        }
    }
    public static void main(String[] args) {
        TableContext.getTables();
    }
    /**
    * @Name loadTableInfos
    * @Description 根据表名查询表中的所有字段
    * @Author wen
    * @Date 2020/3/30
    */
    private static void loadTableInfos(DatabaseMetaData dbmd, String tableName, TableInfo tableInfo, TypeConvertor databaseType2JavaTypeConvertor, TypeConvertor databaseType2JdbcTypeConvertor) throws SQLException {
        ResultSet resultSet = dbmd.getColumns(null, "%", tableName, "%");
        while (resultSet.next()) {
            String columnName = resultSet.getString("COLUMN_NAME");     //获取字段名
            String fieldName = StringUtil.toCamel(columnName);                      //转为驼峰命名
            String columnType = resultSet.getString("TYPE_NAME");          //获取字段类型
            String fieldType = databaseType2JavaTypeConvertor.exec(columnType);             //转为java字段类型
            String jdbcType = databaseType2JdbcTypeConvertor.exec(columnType);             //转为jdbcType字段类型
            ColumnInfo columnInfo = new ColumnInfo();
            columnInfo.setField(new ColumnInfo.Field(columnName, fieldName));
            columnInfo.setType(new ColumnInfo.Type(columnType, fieldType, jdbcType));
            columnInfo.setRemarks(resultSet.getString("REMARKS"));          //设置备注信息
            columnInfo.setAutoincrement("YES".equals(resultSet.getString("IS_AUTOINCREMENT")) ? 1 : 0);  //设置主键是否自增
            columnInfo.setKeyType(0);                                                     //设置键类型
            tableInfo.getColumns().put(resultSet.getString("COLUMN_NAME"), columnInfo);
        }
    }

    /**
     * @Name getTypeConvertor
     * @Description 获取类型转换器
     * @Author wen
     * @Date 2020/3/30
     */
//    private static void getTypeConvertor() {
//        String classPath = DBManager.getConf().getTypeConvertorClassPath();
//        if (StringUtil.isNotEmpty(classPath)) {
//            try {
//                Class<?> clazz = Class.forName(classPath);
//                convertor = (TypeConvertor) clazz.newInstance();
//            } catch (Exception e) {
//                System.out.println("指定的类加载器路径错误:" + e);
//                convertor = new SimpleTypeConvertor();
//            }
//        } else {
//            convertor = new SimpleTypeConvertor();
//        }
//    }

    private TableContext() {
    }

    public static Map<String, TableInfo> getTables() {
        return tables;
    }

}
